/*
 * Modified sample code from mgwt showcase
 * Copyright 2010 Daniel Kurka
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package de.dhbw.vs.permachat.client.activities.chat;

import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import org.fusesource.restygwt.client.Method;
import org.fusesource.restygwt.client.MethodCallback;

import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.web.bindery.event.shared.EventBus;
import com.googlecode.mgwt.dom.client.event.tap.TapEvent;
import com.googlecode.mgwt.dom.client.event.tap.TapHandler;
import com.googlecode.mgwt.mvp.client.MGWTAbstractActivity;
import com.googlecode.mgwt.ui.client.dialog.Dialogs;

import de.dhbw.vs.permachat.client.ActionEvent;
import de.dhbw.vs.permachat.client.ActionNames;
import de.dhbw.vs.permachat.client.ClientFactory;
import de.dhbw.vs.permachat.client.UserInformation;
import de.dhbw.vs.permachat.client.dto.ChatMessage;
import de.dhbw.vs.permachat.client.dto.ChatRoom;
import de.dhbw.vs.permachat.client.dto.ChatUser;
import de.dhbw.vs.permachat.client.rest.ChatServiceAsync;

/**
 * @author Daniel Kurka
 * 
 */
public class ChatActivity extends MGWTAbstractActivity {
	private static final Logger LOGGER = Logger.getLogger(ChatActivity.class.toString());
	private static final int INITIAL_MESSAGE_COUNT = 10;
	private static final int MESSAGE_LOAD_INTERVAL = 5000;

	private final ClientFactory clientFactory;
	private ChatView view;
	private ChatRoom chatRoom;
	
	private Timer messageLoadTimer;
	private long lastMessageId;
	private ChatUser user;
	private boolean messageLoadInProgress;

	public ChatActivity(ClientFactory clientFactory, ChatPlace place) {
		this.clientFactory = clientFactory;
		user = UserInformation.getUser();
		
		chatRoom = place.getChatRoom();
		lastMessageId = -1;
	}

	@Override
	public void start(AcceptsOneWidget panel, final EventBus eventBus) {
		view = clientFactory.getChatView();
		view.reset();

		view.setLeftButtonText("Rooms");
		view.setTitle("Room " + this.chatRoom.getName());

		addHandlerRegistration(view.getBackButton().addTapHandler(
				new TapHandler() {

					@Override
					public void onTap(TapEvent event) {
						ActionEvent.fire(eventBus, ActionNames.BACK);

					}
				}));
		
		addHandlerRegistration(view.getSendButton().addTapHandler(
				new TapHandler() {
			
			@Override
			public void onTap(TapEvent event) {
				sendMessage();
			}
		}));
		
		addHandlerRegistration(view.getInputBoxSender().addKeyUpHandler(new KeyUpHandler() {
			
			@Override
			public void onKeyUp(KeyUpEvent event) {
				if(KeyCodes.KEY_ENTER == event.getNativeKeyCode()){
					sendMessage();
				}
			}
		}));

		panel.setWidget(view);
		
		messageLoadInProgress = false;
		loadInitialChatMessages();

	}

	private void loadInitialChatMessages() {
		this.loadMessages(INITIAL_MESSAGE_COUNT, -1, true, true, false);
	}

	private void schedulePeriodicalTimer() {
		this.messageLoadTimer = new Timer() {
			
			@Override
			public void run() {
				loadMessages(-1, lastMessageId, false, false, false);
			}
		};
		
		this.messageLoadTimer.scheduleRepeating(MESSAGE_LOAD_INTERVAL);
	}
	
	private void loadMessages(int count, long lastId, final boolean showProgressIndicator, final boolean startScheduledTimer, final boolean afterSendSucceeded){
		if(showProgressIndicator){
			this.view.showProgressIndicator();
		}
		
		if(!messageLoadInProgress){
			messageLoadInProgress = true;
			
			ChatServiceAsync chatService = this.clientFactory.getChatService();
			chatService.listChatMessages(this.chatRoom.getName(), new Integer(count), new Long(lastId), new MethodCallback<List<ChatMessage>>() {

				@Override
				public void onSuccess(Method method, List<ChatMessage> response) {
					LOGGER.info("Received chat messages");
					
					if(response != null && !response.isEmpty()){
						ChatMessage lastMessage = response.get(response.size() -1);
						if(lastMessage != null){
							lastMessageId = lastMessage.getMessageId();
							LOGGER.info("Last received message id: " + lastMessageId);
						}
					}
					
					messageLoadInProgress = false;
					
					view.addChatMessages(response);
					
					//if(showProgressIndicator){
						view.hideProgressIndicator();
					//}
					
					if(startScheduledTimer){
						schedulePeriodicalTimer();
					}
					
					if(afterSendSucceeded){
						view.sendSucceeded();
					}
				}
				
				@Override
				public void onFailure(Method method, Throwable exception) {
					LOGGER.severe("Exception while getting chat messages: "
							+ exception.getMessage());
					
					if(showProgressIndicator){
						view.hideProgressIndicator();
					}
					
					Dialogs.alert("Server Call Exception", "Server call failed, message: "
							+ exception.getMessage(), null);
				}
				
			});
		}
	}
	
	/**
	   * {@inheritDoc}
	   * 
	   * onStop is overriden to automatically stop the message load timer
	   */
	@Override
	  public void onStop() {
	    super.onStop();

	    if(this.messageLoadTimer != null){
	    	this.messageLoadTimer.cancel();
	    }
	  }
	
	private void sendMessage(){
		ChatMessage message = new ChatMessage();
		message.setTextMessage(view.getInputBox().getText());
		message.setChatUser(user.getName());
		message.setPostedAt(new Date());
		
		ChatServiceAsync chatService = this.clientFactory.getChatService();
		chatService.postChatMessage(chatRoom.getName(), message, new MethodCallback<Void>() {
			
			@Override
			public void onSuccess(Method method, Void response) {
				view.getInputBox().setText("");
				messageLoadTimer.cancel();
				loadMessages(-1, lastMessageId, true, true, true);
			}
			
			@Override
			public void onFailure(Method method, Throwable exception) {
				LOGGER.severe("Exception while sending chat message: "
						+ exception.getMessage());
				
				Dialogs.alert("Server Call Exception", "Server call failed, message: "
						+ exception.getMessage(), null);
			}
		});
		
	}
}
